import Recorder from 'recorder-js';

/**
 * 录音管理器 - 基于Recorder.js实现
 * 提供录音权限检测、录音控制、音频文件生成等功能
 */
class AudioRecorder {
  constructor() {
    this.recorder = null;
    this.isRecording = false;
    this.audioContext = null;
    this.mediaStream = null;
    this.audioData = null;
    this.targetSampleRate = 16000; // 期望采样率16kHz
    this.sampleRate = null; // 实际AudioContext采样率
    this.recordingStartTime = null; // 录音开始时间
    this.recordingEndTime = null; // 录音结束时间
    this.analyser = null; // 音频分析器
    this.dataArray = null; // 音频数据数组
    this.volumeInterval = null; // 音量检测定时器

    // 回调函数
    this.onStartCallback = null;
    this.onStopCallback = null;
    this.onErrorCallback = null;
    this.volumeCallback = null; // 音量回调函数
  }

  /**
   * 获取getUserMedia方法（兼容各种浏览器）
   * @returns {Function|null} getUserMedia方法
   */
  getUserMediaCompat() { // eslint-disable-line class-methods-use-this
    // 优先使用标准的navigator.mediaDevices.getUserMedia
    if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
      return navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);
    }

    // 兼容旧版Chrome/Firefox
    const getUserMedia = navigator.getUserMedia
                         || navigator.webkitGetUserMedia
                         || navigator.mozGetUserMedia
                         || navigator.msGetUserMedia;

    if (getUserMedia) {
      // 转换为Promise形式的API
      return (constraints) => new Promise((resolve, reject) => {
        getUserMedia.call(navigator, constraints, resolve, reject);
      });
    }

    return null;
  }

  /**
   * 检查当前网页是否有录音权限
   * @returns {Promise<boolean>} 是否有录音权限
   */
  async checkPermission() {
    try {
      // 检查浏览器是否支持getUserMedia
      const getUserMedia = this.getUserMediaCompat();
      if (!getUserMedia) {
        console.warn('浏览器不支持录音功能');
        console.log('浏览器信息:', {
          userAgent: navigator.userAgent,
          hasMediaDevices: !!navigator.mediaDevices,
          hasGetUserMedia: !!navigator.getUserMedia,
          hasWebkitGetUserMedia: !!navigator.webkitGetUserMedia
        });
        return false;
      }

      // 请求麦克风权限
      const stream = await getUserMedia({
        audio: {
          channelCount: 1, // 单声道
          echoCancellation: true,
          noiseSuppression: true
        }
      });

      // 立即停止流，只是检查权限
      stream.getTracks().forEach(track => track.stop());

      return true;
    } catch (error) {
      console.error('录音权限检查失败:', error);
      console.log('浏览器信息:', {
        userAgent: navigator.userAgent,
        hasMediaDevices: !!navigator.mediaDevices,
        hasGetUserMedia: !!navigator.getUserMedia,
        hasWebkitGetUserMedia: !!navigator.webkitGetUserMedia
      });
      this.handleError('PERMISSION_DENIED', '用户拒绝了录音权限或浏览器不支持录音');
      return false;
    }
  }

  /**
   * 初始化录音器
   * @returns {Promise<boolean>} 初始化是否成功
   */
  async initialize() {
    try {
      console.log('开始初始化录音器...');

      // 检查权限
      console.log('检查录音权限...');
      const hasPermission = await this.checkPermission();
      if (!hasPermission) {
        console.error('录音权限检查失败');
        return false;
      }
      console.log('录音权限检查通过');

      // 创建AudioContext
      console.log('创建AudioContext...');
      const AudioContextClass = window.AudioContext || window.webkitAudioContext;
      this.audioContext = new AudioContextClass();
      this.sampleRate = this.audioContext.sampleRate;
      if (this.sampleRate !== this.targetSampleRate) {
        console.warn(`AudioContext采样率(${this.sampleRate})与期望值(${this.targetSampleRate})不同，将尝试在Recorder中重采样。`);
      }
      console.log('AudioContext创建成功，状态:', this.audioContext.state);

      // 初始化Recorder
      console.log('初始化Recorder...');
      this.recorder = new Recorder(this.audioContext, {
        type: 'wav',
        sampleRate: this.targetSampleRate,
        bitRate: 16,
        numChannels: 0.5 // recorder-js 使用 numChannels 设置单声道
      });
      console.log('Recorder初始化成功');

      console.log('录音器初始化完成');
      return true;
    } catch (error) {
      console.error('录音器初始化失败:', error);
      const errorMessage = error.message || error.toString() || '未知错误';
      this.handleError('INIT_FAILED', `录音器初始化失败: ${errorMessage}`);
      return false;
    }
  }

  /**
   * 开始录音
   * @returns {Promise<boolean>} 开始录音是否成功
   */
  async startRecording() {
    try {
      console.log('准备开始录音...');

      if (this.isRecording) {
        console.warn('录音已在进行中');
        return false;
      }

      // 检查录音器是否已初始化
      if (!this.recorder) {
        console.log('录音器未初始化，正在初始化...');
        const initialized = await this.initialize();
        if (!initialized) {
          console.error('录音器初始化失败');
          return false;
        }
        console.log('录音器初始化成功');
      }

      // 检查浏览器支持
      const getUserMedia = this.getUserMediaCompat();
      if (!getUserMedia) {
        throw new Error('浏览器不支持getUserMedia API');
      }

      console.log('正在获取媒体流...');
      // 获取媒体流
      this.mediaStream = await getUserMedia({
        audio: {
          channelCount: 1,
          echoCancellation: true,
          noiseSuppression: true
        }
      });
      console.log('媒体流获取成功');

      // 检查录音器状态
      if (!this.recorder) {
        throw new Error('录音器未正确初始化');
      }

      // 确保 AudioContext 处于运行状态（火狐浏览器兼容性处理）
      if (this.audioContext && this.audioContext.state !== 'running') {
        console.log(`AudioContext 状态为 ${this.audioContext.state}，尝试恢复...`);
        try {
          if (this.audioContext.state === 'suspended') {
            await this.audioContext.resume();
            console.log('AudioContext 已恢复为运行状态:', this.audioContext.state);
          } else if (this.audioContext.state === 'closed') {
            // AudioContext 已关闭，需要重新创建
            console.log('AudioContext 已关闭，重新创建...');
            const AudioContextClass = window.AudioContext || window.webkitAudioContext;
            this.audioContext = new AudioContextClass();
            this.sampleRate = this.audioContext.sampleRate;
            // 重新初始化 Recorder
            this.recorder = new Recorder(this.audioContext, {
              type: 'wav',
              sampleRate: this.targetSampleRate,
              bitRate: 16,
              numChannels: 0.5
            });
          }
        } catch (resumeError) {
          console.warn('恢复 AudioContext 失败:', resumeError);
          // 如果恢复失败，尝试重新创建 AudioContext
          console.log('尝试重新创建 AudioContext...');
          try {
            const AudioContextClass = window.AudioContext || window.webkitAudioContext;
            this.audioContext = new AudioContextClass();
            this.sampleRate = this.audioContext.sampleRate;
            // 重新初始化 Recorder
            this.recorder = new Recorder(this.audioContext, {
              type: 'wav',
              sampleRate: this.targetSampleRate,
              bitRate: 16,
              numChannels: 0.5
            });
            console.log('AudioContext 和 Recorder 重新创建成功');
          } catch (recreateError) {
            console.error('重新创建 AudioContext 失败:', recreateError);
            throw new Error(`无法恢复或创建 AudioContext: ${recreateError.message}`);
          }
        }
      }

      console.log('正在启动录音...');
      console.log('AudioContext 状态:', this.audioContext ? this.audioContext.state : 'null');
      console.log('媒体流状态:', this.mediaStream ? {
        active: this.mediaStream.active,
        tracks: this.mediaStream.getTracks().map(t => ({
          kind: t.kind,
          enabled: t.enabled,
          readyState: t.readyState
        }))
      } : 'null');

      // 记录录音开始时间
      this.recordingStartTime = Date.now();
      this.recordingEndTime = null;

      // 开始录音 - 先初始化录音器，然后开始录音
      // 火狐浏览器中，需要确保 AudioContext 处于运行状态
      if (this.audioContext && this.audioContext.state === 'suspended') {
        await this.audioContext.resume();
      }

      console.log('初始化 Recorder...');
      await this.recorder.init(this.mediaStream);
      console.log('Recorder 初始化成功');
      await this.recorder.start();
      this.isRecording = true;
      this.audioData = null;

      // 自动开始音量检测
      this.startVolumeDetection();

      console.log('录音已开始');
      this.handleStart();
      return true;
    } catch (error) {
      console.error('开始录音失败:', error);
      const errorMessage = error.message || error.toString() || '未知错误';
      this.handleError('START_FAILED', `开始录音失败: ${errorMessage}`);

      // 清理资源
      if (this.mediaStream) {
        this.mediaStream.getTracks().forEach(track => track.stop());
        this.mediaStream = null;
      }

      return false;
    }
  }

  /**
   * 停止录音
   * @returns {Promise<boolean>} 停止录音是否成功
   */
  async stopRecording() {
    try {
      if (!this.isRecording) {
        console.warn('当前没有在录音');
        return false;
      }

      // 记录录音结束时间
      this.recordingEndTime = Date.now();

      // 停止录音
      const { blob } = await this.recorder.stop();
      this.audioData = blob;
      this.isRecording = false;

      // 停止媒体流
      if (this.mediaStream) {
        this.mediaStream.getTracks().forEach(track => track.stop());
        this.mediaStream = null;
      }

      // 清理音量分析
      this.cleanupVolumeAnalysis();

      console.log('停止录音');
      this.handleStop();
      return true;
    } catch (error) {
      console.error('停止录音失败:', error);
      const errorMessage = error.message || error.toString() || '未知错误';
      this.handleError('STOP_FAILED', `停止录音失败: ${errorMessage}`);
      return false;
    }
  }

  /**
   * 获取录音文件信息
   * @returns {Promise<Object|null>} 录音文件信息
   */
  async getRecordingInfo() {
    try {
      if (!this.audioData) {
        console.warn('没有录音数据');
        return null;
      }

      // 创建File对象
      const fileName = `recording_${Date.now()}.wav`;
      const file = new File([this.audioData], fileName, {
        type: 'audio/wav',
        lastModified: Date.now()
      });

      // 计算音频时长（使用时间戳计算，更准确）
      let duration = 0;
      if (this.recordingStartTime && this.recordingEndTime) {
        duration = Math.round((this.recordingEndTime - this.recordingStartTime) / 1000 * 100) / 100; // 转换为秒，保留2位小数
      } else if (this.recordingStartTime) {
        // 如果还在录音中，计算当前时长
        duration = Math.round((Date.now() - this.recordingStartTime) / 1000 * 100) / 100;
      }

      const info = {
        file: file,
        fileName: fileName,
        fileSize: this.audioData.size,
        duration: duration,
        sampleRate: this.targetSampleRate,
        format: 'wav',
        mimeType: 'audio/wav'
      };

      console.log('录音信息:', info);
      return info;
    } catch (error) {
      console.error('获取录音信息失败:', error);
      const errorMessage = error.message || error.toString() || '未知错误';
      this.handleError('GET_INFO_FAILED', `获取录音信息失败: ${errorMessage}`);
      return null;
    }
  }

  /**
   * 获取当前录音时长（录音过程中）
   * @returns {number} 当前录音时长（秒）
   */
  getCurrentDuration() {
    if (!this.recordingStartTime) {
      return 0;
    }

    const endTime = this.recordingEndTime || Date.now();
    return Math.round((endTime - this.recordingStartTime) / 1000 * 100) / 100;
  }

  /**
   * 清理音量分析
   * @private
   */
  cleanupVolumeAnalysis() {
    if (this.volumeInterval) {
      clearInterval(this.volumeInterval);
      this.volumeInterval = null;
    }

    this.analyser = null;
    this.dataArray = null;
    console.log('音量分析已清理');
  }

  /**
   * 获取当前音量
   * @returns {number} 音量值 (0-100)
   */
  getCurrentVolume() {
    // 如果分析器不存在，尝试创建它
    if (!this.analyser && this.audioContext && this.mediaStream) {
      try {
        // 创建音频源
        const source = this.audioContext.createMediaStreamSource(this.mediaStream);
        console.log('source', source);

        // 创建分析器
        this.analyser = this.audioContext.createAnalyser();
        this.analyser.fftSize = 256; // 设置FFT大小
        this.analyser.smoothingTimeConstant = 0.8; // 平滑时间常数

        // 连接音频源到分析器
        source.connect(this.analyser);

        // 创建数据数组
        const bufferLength = this.analyser.frequencyBinCount;
        this.dataArray = new Uint8Array(bufferLength);

        console.log('音量分析器已创建');
      } catch (error) {
        console.error('创建音量分析器失败:', error);
        return 0;
      }
    }

    if (!this.analyser || !this.dataArray) {
      return 0;
    }

    try {
      // 获取频域数据
      this.analyser.getByteFrequencyData(this.dataArray);

      // 计算平均音量
      let sum = 0;
      for (let i = 0; i < this.dataArray.length; i++) {
        sum += this.dataArray[i];
      }
      const average = sum / this.dataArray.length;

      // 转换为百分比 (0-100)
      return Math.round((average / 255) * 100);
    } catch (error) {
      console.error('获取音量失败:', error);
      return 0;
    }
  }

  /**
   * 开始实时音量检测
   * @param {Function} callback 音量回调函数，参数为音量值(0-100)
   * @param {number} interval 检测间隔(毫秒)，默认100ms
   */
  startVolumeDetection(callback, interval = 100) {
    if (!this.isRecording) {
      console.warn('录音未开始，无法检测音量');
      return false;
    }

    if (this.volumeInterval) {
      console.warn('音量检测已在运行');
      return false;
    }

    // 如果提供了回调函数，则设置它
    if (callback) {
      this.volumeCallback = callback;
    }

    this.volumeInterval = setInterval(() => {
      const volume = this.getCurrentVolume();
      if (this.volumeCallback) {
        this.volumeCallback(volume);
      } else {
        // 默认行为：只在控制台输出音量信息
        console.log('当前音量:', volume);
      }
    }, interval);

    console.log('开始实时音量检测');
    return true;
  }

  /**
   * 停止实时音量检测
   */
  stopVolumeDetection() {
    if (this.volumeInterval) {
      clearInterval(this.volumeInterval);
      this.volumeInterval = null;
      this.volumeCallback = null;
      console.log('停止实时音量检测');
    }
  }

  /**
   * 清除录音数据
   */
  clearRecording() {
    this.audioData = null;
    this.recordingStartTime = null;
    this.recordingEndTime = null;
    this.stopVolumeDetection();
    console.log('录音数据已清除');
  }

  /**
   * 销毁录音器
   */
  destroy() {
    if (this.isRecording) {
      this.stopRecording();
    }

    // 清理音量检测
    this.stopVolumeDetection();

    if (this.mediaStream) {
      this.mediaStream.getTracks().forEach(track => track.stop());
      this.mediaStream = null;
    }

    if (this.audioContext) {
      this.audioContext.close();
      this.audioContext = null;
    }

    this.recorder = null;
    this.audioData = null;
    this.analyser = null;
    this.dataArray = null;
    console.log('录音器已销毁');
  }

  /**
   * 设置开始录音回调
   * @param {Function} callback 回调函数
   */
  onStart(callback) {
    this.onStartCallback = callback;
  }

  /**
   * 设置结束录音回调
   * @param {Function} callback 回调函数
   */
  onStop(callback) {
    this.onStopCallback = callback;
  }

  /**
   * 设置录音失败回调
   * @param {Function} callback 回调函数
   */
  onError(callback) {
    this.onErrorCallback = callback;
  }

  /**
   * 设置音量变化回调
   * @param {Function} callback 音量回调函数，参数为音量值(0-100)
   */
  onVolumeChange(callback) {
    this.volumeCallback = callback;
    console.log('音量回调函数已设置');
  }

  /**
   * 处理开始录音回调
   * @private
   */
  handleStart() {
    if (this.onStartCallback) {
      this.onStartCallback();
    }
  }

  /**
   * 处理结束录音回调
   * @private
   */
  handleStop() {
    if (this.onStopCallback) {
      this.onStopCallback();
    }
  }

  /**
   * 处理录音错误回调
   * @private
   * @param {string} errorCode 错误代码
   * @param {string} errorMessage 错误信息
   */
  handleError(errorCode, errorMessage) {
    const error = {
      code: errorCode,
      message: errorMessage,
      timestamp: Date.now()
    };

    console.error('录音错误:', error);

    if (this.onErrorCallback) {
      this.onErrorCallback(error);
    }
  }

  /**
   * 获取当前录音状态
   * @returns {Object} 录音状态信息
   */
  getStatus() {
    return {
      isRecording: this.isRecording,
      hasAudioData: !!this.audioData,
      sampleRate: this.sampleRate,
      audioContextState: this.audioContext ? this.audioContext.state : null,
      hasRecorder: !!this.recorder,
      hasMediaStream: !!this.mediaStream,
      currentDuration: this.getCurrentDuration(),
      recordingStartTime: this.recordingStartTime,
      recordingEndTime: this.recordingEndTime,
      currentVolume: this.getCurrentVolume(),
      isVolumeDetectionActive: !!this.volumeInterval
    };
  }

  /**
   * 调试方法 - 检查录音器状态
   */
  debugStatus() {
    console.log('=== 录音器调试信息 ===');
    console.log('录音状态:', this.isRecording);
    console.log('录音器实例:', this.recorder);
    console.log('AudioContext:', this.audioContext);
    console.log('AudioContext状态:', this.audioContext ? this.audioContext.state : 'null');
    console.log('媒体流:', this.mediaStream);
    console.log('音频数据:', this.audioData);
    console.log('采样率:', this.sampleRate);
    console.log('========================');
  }
}

// 创建全局单例
const audioRecorder = new AudioRecorder();

export default audioRecorder;
